import java.util.ArrayList;


public class State {
	int playerID;  
	final int ID;
	int[][] gameBoard;
	int lastRow, lastCol;
	private static final int tokensToWin = 3;
	
	ArrayList<Integer> openCols; // TODO consider changing to a HashSet

	State(int cols, int rows, int playerID) {
		this.playerID = playerID;
		this.ID = playerID;
		this.gameBoard = new int[cols][rows];
		this.openCols = new ArrayList<Integer>(cols);
		for (int i = 0; i < cols; i++) {
			this.openCols.add(i);
		}
	}
	
	State(State s) {
		this.playerID = s.playerID;
		this.lastCol = s.lastCol;
		this.lastRow = s.lastRow;
		this.ID = s.ID;
		
		this.gameBoard = new int[s.gameBoard.length][s.gameBoard[0].length];
		for (int col = 0; col < gameBoard.length; col++) {
			for (int row = 0; row < gameBoard[0].length; row++) {
				this.gameBoard[col][row] = s.gameBoard[col][row];
			}	
		}
		
		this.openCols = new ArrayList<Integer>(s.openCols.size());
		for (int i = 0; i < s.openCols.size(); i++) {
			this.openCols.add(s.openCols.get(i));
		}
	}
	

	
	void print() {
		for (int row = gameBoard[0].length - 1; row >= 0; row--) {
			for (int col = 0; col < gameBoard.length; col++) {
				System.out.print(gameBoard[col][row]);
			}	
			System.out.println();
		}
	}
	
	void print(String space) {
		for (int row = gameBoard[0].length - 1; row >= 0; row--) {
			System.out.print(space);
			for (int col = 0; col < gameBoard.length; col++) {
				System.out.print(gameBoard[col][row]);
			}	
			System.out.println();
		}
	}
	
	void printAll() {
		for (int row = gameBoard[0].length - 1; row >= 0; row--) {
			for (int col = 0; col < gameBoard.length; col++) {
				System.out.print(gameBoard[col][row]);
			}	
			System.out.println();
		}
		System.out.println("lastCol: " + lastCol + ", lastRow: " + lastRow);
		System.out.println("playerID: " + playerID);
		System.out.println("ID: " + ID);
	}
	
	void insertCoin(int col, int playerID) {
		int row;
		for (row = 0; row < gameBoard[0].length; row++) {
			if (gameBoard[col][row] == 0) {
				gameBoard[col][row] = playerID;
				lastRow = row;
				lastCol = col;
				break;
			}
		}
		if (row + 1 == gameBoard[0].length) {
			openCols.remove((Integer)col);
		}
	}
	
	void switchTurn() {
		playerID = playerID == 1 ? 2 : 1;
	}
	
	
	int terminateTest() {
//		ArrayList<Integer> openCols = openCols;
//		int lastRow = s.lastRow, lastCol = lastCol;
//		int[][] gameBoard = gameBoard;
		int currentRow = lastRow;
		int currentCol = lastCol;
		int count = 1;
		if (currentCol != 0){ //Checks left horizontally
			while (gameBoard[currentCol][currentRow] == gameBoard[--currentCol][currentRow]){
				count++;
				if (currentCol < 1) break;
			}
		}
		currentCol = lastCol;
		if (currentCol < gameBoard.length-1){//Checks right horizontally
			while (gameBoard[currentCol][currentRow] == gameBoard[++currentCol][currentRow]){
				count++;
				if (currentCol > gameBoard.length-2) break;
			}
		}
		if (count >= tokensToWin) return gameBoard[lastCol][lastRow];
		currentRow = lastRow;
		currentCol = lastCol;
		count = 1;
		if (currentRow > 0){ //Checks vertically up
			while (gameBoard[currentCol][currentRow] == gameBoard[currentCol][--currentRow]){
				count++;
				if (currentRow < 1) break;
			}
		}
		if (count >= tokensToWin) return gameBoard[lastCol][lastRow];
		currentRow = lastRow;
		currentCol = lastCol;
		count = 1;
		if (currentRow > 0 && currentCol > 0){ //Checks diagonally lower left to upper right, downwards
			while (gameBoard[currentCol][currentRow] == gameBoard[--currentCol][--currentRow]){
				count++;
				if (currentRow < 1 || currentCol < 1) break;
			}
		}
		currentRow = lastRow;
		currentCol = lastCol;
		if (currentRow < gameBoard[currentRow].length-1 && currentCol < gameBoard.length-1){ //Checks diagonally lower left to upper right, upwards
			while (gameBoard[currentCol][currentRow] == gameBoard[++currentCol][++currentRow]){
				count++;
				if (currentRow > gameBoard[currentRow].length-2 || currentCol > gameBoard.length-2) break;
			}
		}
		if (count >= tokensToWin) return gameBoard[lastCol][lastRow];
		currentRow = lastRow;
		currentCol = lastCol;
		count = 1;
		if (currentRow > 0 && currentCol < gameBoard.length-1){ //Checks diagonally upper left to lower right, downwards
			while (gameBoard[currentCol][currentRow] == gameBoard[++currentCol][--currentRow]){
				count++;
				if (currentRow < 1 || currentCol > gameBoard.length-2) break;
			}
		}
		currentRow = lastRow;
		currentCol = lastCol;
		if (currentRow < gameBoard[currentRow].length-1 && currentCol > 0){ //Checks diagonally upper left to lower right, upwards
			while (gameBoard[currentCol][currentRow] == gameBoard[--currentCol][++currentRow]){
				count++;
				if (currentRow > gameBoard[currentRow].length-2 || currentCol < 1) break;
			}
		}
		if (count >= tokensToWin) return gameBoard[lastCol][lastRow];
		if (openCols.isEmpty()) {
			return 3;
		}
		return 0; //No winner
	}

	

}
